#include "AS5047P.h"

float AS5047P_Read(AS5047P_HandleTypeDef *has5047p);
static struct AS5047P_pf AS5047P_pf = 
{
	.read = AS5047P_Read,
};

void AS5047P_Init(AS5047P_HandleTypeDef *has5047p, SPI_HandleTypeDef *hspi, GPIO_TypeDef *pCS_GPIOx, uint16_t uCS_GPIO_Pin)
{
    has5047p->hspi = hspi;
	has5047p->CS_GPIOx = pCS_GPIOx;
	has5047p->CS_GPIO_Pin = uCS_GPIO_Pin;
	has5047p->pf = &AS5047P_pf;
    HAL_GPIO_WritePin(pCS_GPIOx, uCS_GPIO_Pin, GPIO_PIN_SET);
}


static uint8_t EvenParity(uint16_t data)
{
    uint8_t parity = 0;
    while (data)
    {
        if (data & 0x1)
        {
            parity = !parity;
        }
        data >>= 1;
    }
    return (!parity);
}

_Noreturn static void AS5047P_Error_Handler();

uint16_t AS5047P_ReceiveData(SPI_HandleTypeDef *hspi, GPIO_TypeDef *CS_GPIOx, uint16_t CS_GPIO_Pin)
{
    uint16_t DATA_R = 0;
    uint16_t DATA_T = 0xFFFF;
    if(hspi == NULL) AS5047P_Error_Handler();


    HAL_GPIO_WritePin(CS_GPIOx, CS_GPIO_Pin, GPIO_PIN_RESET);
    HAL_SPI_TransmitReceive(hspi, (uint8_t *)&DATA_T, (uint8_t *)&DATA_R, 1, 0x01);
    HAL_GPIO_WritePin(CS_GPIOx, CS_GPIO_Pin, GPIO_PIN_SET);

    if ((DATA_R == 0)||(DATA_R == 0xFFFF)) DATA_R = 1;
    //english comment:
    //The probability of 'DATA_R' being exactly 0 is very small.
    //If it is exactly zero, it is highly likely that the SPI reception failed.
    //In that case, we set it to '1', as it cannot pass the even parity check.
    //chinese comment:
    //中文注释:
    //'DATA_R'刚好等于0的概率很小, 如果它刚好等于零那么很大概率是spi接受失败,那么我们使其等于1,不能通过偶校验
    return DATA_R;
}


float AS5047P_Read(AS5047P_HandleTypeDef *has5047p)
{
    uint16_t data = AS5047P_ReceiveData(has5047p->hspi, has5047p->CS_GPIOx, has5047p->CS_GPIO_Pin);
    if(!EvenParity(data))
	{
		has5047p->angle = 0;
		return 0;
	}
    else
    {
        has5047p->angle = (data & 0x3fff) * 360.f / 0x4000;
        return has5047p->angle;
    }
}

_Noreturn static void AS5047P_Error_Handler()
{
    __disable_irq();
    while (1)
    {
    }
}
